package cc.rengu.igas.bomp.common.util;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author: zhangxuran
 * @Date: 2020/4/10 9:23
 * @Description: 比较两个对象不同的数据
 */
public class CompareFieldsUtil {

    /**
     * @param oldObj    进行属性比较的对象1
     * @param newObj    进行属性比较的对象2
     * @param ignoreArr 选择忽略比较的属性数组
     * @return 属性差异比较结果 map
     */
    public static String compareFields(Object oldObj, Object newObj, String[] ignoreArr) {
        StringBuilder str = new StringBuilder();
        try {
            List<String> ignoreList = null;
            if (ignoreArr != null && ignoreArr.length > 0) {
                ignoreList = Arrays.asList(ignoreArr);
            }

            //只有两个对象都是同一类型才有可比性
            if (oldObj.getClass() == newObj.getClass()) {
                Class clazz = oldObj.getClass();
                //获取object的属性描述
                PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                    String name = pd.getName();
                    if (ignoreList != null && ignoreList.contains(name)) {
                        continue;
                    }
                    //获取属性的get方法
                    Method readMethod = pd.getReadMethod();
                    //在oldObj上调用get方法等同于获得oldObj的属性值
                    Object o1 = readMethod.invoke(oldObj);
                    //在newObj上调用get方法等同于获得newObj的属性值
                    Object o2 = readMethod.invoke(newObj);
                    //如果此属性是时间
                    if (o1 instanceof Timestamp) {
                        o1 = new Date(((Timestamp) o1).getTime());
                    }
                    if (o2 instanceof Timestamp) {
                        o2 = new Date(((Timestamp) o2).getTime());
                    }

                    if (o1 == null && o2 != null) {
                        str.append("字段").append(name).append("从null变更为").append(o2).append(";");
                    }

                    if (o1 != null && o2 == null) {
                        str.append("字段").append(name).append("从").append(o1).append("变更为null;");
                    }

                    if (o1 == null || o2 == null) {
                        continue;
                    }

                    if (!o1.toString().equals(o2.toString())) {
                        str.append("字段").append(name).append("从").append(o1).append("变更为").append(o2).append(";");
                    }
                }
            }
            return str.toString();
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * @param oldObj   进行属性比较的对象1
     * @param newObj   进行属性比较的对象2
     * @param errorArr 不允许修改的属性 （允许old对象为null进行赋值）
     * @return 属性差异比较结果 map
     */
    public static String noAllowModifyFields(Object oldObj, Object newObj, String[] errorArr) {
        StringBuilder str = new StringBuilder();
        try {
            List<String> errorList = null;
            if (errorArr != null && errorArr.length > 0) {
                errorList = Arrays.asList(errorArr);
            }

            //只有两个对象都是同一类型才有可比性
            if (oldObj.getClass() == newObj.getClass()) {
                Class clazz = oldObj.getClass();
                //获取object的属性描述
                PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                    String name = pd.getName();
                    if (errorList != null && errorList.contains(name)) {
                        //获取属性的get方法
                        Method readMethod = pd.getReadMethod();
                        //在oldObj上调用get方法等同于获得oldObj的属性值
                        Object o1 = readMethod.invoke(oldObj);
                        if (o1 == null) {
                            continue;
                        }
                        str.append("字段").append(name).append("不能修改;");
                    }
                }
            }
            return str.toString();
        } catch (Exception e) {

            return null;
        }
    }
}
